package IceAssembly;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * Tables that hold valuable information representing the interesting parts of the 
 * source program for assembling it and generating intermediate output for assembling
 * the program. 
 */
public class Table implements Interface {
    
    static public String[][] symbol_table = new String[50][4];
    static public int symbol_row = 0;
    
    static public String[][] error_table = new String[3072][2];
    static public int error_row = 0;
    
    static public String[][] intermediate_file = new String[1023][8];
    static public int intermediate_row = 0;
    static public int start_index=0;
        
    static public File link_error_file  = new File("src//TestPrograms//default_out_error.txt");
    static public File link_inter_file  = new File("src//TestPrograms//default_out_inter.txt");
    static public File link_symbol_file = new File("src//TestPrograms//default_out_symbol.txt");
    
    /**
     * Table for symbols defined in the program as labels, and other pseudo-ops. 
     * General structure of the Symbol Table is: symbol name, location counter, 
     * symbol usage, and substitution string.
     * <p>
     * <b>Changelog:</b><br> 
     * 4/13/08 - Initial code - Peter Dietz 
     * 4/18/08 - changed symbol table to a global variable (public) - Keith Hill
     * 4/19/08 - changed parameter relocation from char to string - Peter Dietz
     * <p><b>Error Conditions Tested:</b><br>
     * None yet
     * <b>Date of module being installed:</b> 4/13/08
     * @author Peter Dietz
     * @param  symbol name to be entered into the table
     * @param  usage how it was declared in the program
     * @param  equvalue substitution string of the variable
     * @return 1 if successfully added to table, 0 if it failed to add to table
     */    
    public int addToSymbolTable (String symbol, String usage, String equvalue) {
        Convert convert_instance = new Convert();
        int status;
        if (symbol_row < symbol_table.length) {
            symbol_table[symbol_row][0] = symbol;
            symbol_table[symbol_row][1] = convert_instance.intToFourHex(Control.location_counter);            
            symbol_table[symbol_row][2] = usage.toUpperCase();
            symbol_table[symbol_row][3] = equvalue;
            symbol_row++;
            status = 1;
            addToSymbolFile();
        } else {
            status =  0;
        }       
        return status;
    }

    /**
     * Error table will have all the errors, and warnings from each line so 
     * they may be printed out when it comes time to print out the errors from
     * each line.
     * <p>
     * <b>Changelog:</b><br>
     * 4/13/08 - Initial code - Peter Dietz 
     * 4/14/08 - changed return from void to int - Peter
     * 4/23/08 - line_num usage was changed to global variable - Peter
     * <p><b>Error Conditions Tested:</b>
     * none yet
     * <b>Date of module being installed:</b> 4/13/08
     * @author Peter Dietz
     * @param  errorcode Error number that is defined in iniErrorTable
     * @return 1 if successfully added to error table, other 0 for failure
     */    
    public int addToErrorTable (String errorcode) {
        
        int status;
        if (error_row < error_table.length) {
            error_table[error_row][0] = String.valueOf(Control.line_num+1);
            error_table[error_row][1] = errorcode;
            error_row++;
            status = 1;
            addToErrorFile();
        } else {
            status =  0;
        }        
        return status;
    }

    /**
     * The machine code summary of each memory consuming instruction from the ICE
     * source code that will be used to generate the intermediate file. 
     * file. 
     * <ul><b>Intermediate File structure:</b></ul>
     * <li>(0) location counter in hex</li><li>(1) the debug status as a word</li>
     * <li>(2) the object code of instruction mnemonic and function in hex</li>
     * <li>(3) the operand value in binary if possible</li><li>(4) relocation 
     * type consisting of a/r/e/c and it might have multiple if it hasn't been determined yet</li></ul>
     * <p>
     * <b>Changelog:</b> 
     * 4/13/08 - Initial code - Peter Dietz 
     * 4/14/08 - implemented, and changed return from void to int - Peter
     * 4/17/08 - added additional parameter relocation_type - Peter
     * 4/23/08 - location counter was changed to global variable - Peter<br>
     * <p><b>Error Conditions Tested:</b>
     * none yet 
     * <b>Date of module being installed:</b> 4/14/08
     * @author Peter Dietz
     * @param  opfunc_code Code for operation-function pair in 5 bits binary
     * @param  operand Parameter as literal or variable. Literals should be in binary format.
     * @param  relocation_type character signifying the location in program
     * @return 1 if successfully added to intermediate file, else 0 if failure
     */    
    public int addToIntermediateFile (String opfunc_code, String operand, String relocation_type) {
        Convert convert_instance = new Convert();
        intermediate_row = Control.location_counter;
        int status;
        if (intermediate_row < intermediate_file.length) {
            intermediate_file[intermediate_row][0] = convert_instance.intToFourHex(Control.location_counter);
            intermediate_file[intermediate_row][1] = Control.debug_status;
            intermediate_file[intermediate_row][2] = opfunc_code;
            intermediate_file[intermediate_row][3] = operand;
            intermediate_file[intermediate_row][4] = relocation_type;
            intermediate_row++;
            status = 1;
            addToInterFile();
        } else {
            status =  0;
        }                
        return status;
    }
    
    /**
     * Performs a lookup in the symbol table for all labels defined acording to
     * the usage <i>usage</i>. If usages were found, then all label names defined
     * as <i>usage</i> will be passed back. <br>
     * <b>Change Log:</b><Br>
     * 4/23/08 - Initial Code - Yogesh Jindal
     * 4/26/08 - Documentation Revised - Peter Dietz
     * <b>Error Conditions Tested</b>
     * none yet
     * <b>Date of module being installed:</b> 4/23/08
     * @author Yogesh Jindal
     * @param usage how the labels usage is defined in the symbol table
     * @return A string array. Position 0 is a bit flag, 0 means that no such usage
     * type was present in the table, and further positions in the array should be 
     * ignored. If position 0 has a value 1, then the usage type was present in the 
     * table. Further positions in the array will contain label names whose usage was
     * defined as specified as <b>usage</b>
     */
    protected String[] getAllLabels(String usage){
        int num_label=0;
        for(int index=0; index<symbol_row; index++){
            if(symbol_table[index][2].compareTo(usage.toUpperCase())==0){
                num_label++;
            }
        }
        String[] label_string = new String[num_label+1];
        if(num_label==0){
            label_string = new String[2];
            label_string[0] = "0"; label_string[1]="";
        }else{
            label_string[0] = "1"; 
        }
        num_label=1;
        for(int index=0; index<symbol_row; index++){
            if(symbol_table[index][2].compareTo(usage.toUpperCase())==0){
                label_string[num_label]=symbol_table[index][0];
                num_label++;
            }
        }
        return label_string;
    }
    /**
    * Creates a text file for the intermediate file and dumps the current contents 
    * of the intermediate table to the file.
    * <p>
    * <b>Change Log:</b><br>
    * 4/24/08 - Initial Code - Yogesh Jindal<br>
    * 4/26/08 - Documentation Revised - Peter Dietz<br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * none yet<br>
    * <b>Date of module being installed:</b> 4/24/08
    * @author Yogesh Jindal
    */
    public void addToInterFile(){        
        try{
            link_inter_file.createNewFile();
            BufferedWriter bw = new BufferedWriter(new FileWriter(link_inter_file));
            for(int i=start_index; i<intermediate_row; i++){                
                bw.write(intermediate_file[i][0]+"\t"+intermediate_file[i][1]+"\t"+intermediate_file[i][2]+"\t"+intermediate_file[i][3]+"\t"+intermediate_file[i][4]);
                bw.write("\n");
            }
            bw.close();
        }catch(IOException e){
            System.out.println("Writing to error file failed");
        }
        
    }
        /**
        * Creates a text file for the error file and dumps the current contents 
        * of the error table to the file.
        * <p>
        * <b>Change Log:</b><br>
        * 4/24/08 - Initial Code - Yogesh Jindal<br>
        * 4/26/08 - Documentation Revised - Peter Dietz<br>
        * <p>
        * <b>Error Conditions Tested:</b><br>
        * INTERNAL: Writing to error file failed<br>
        * <b>Date of module being installed:</b> 4/24/08
        * @author Yogesh Jindal
        */
    public void addToErrorFile(){        
        try{
            link_error_file.createNewFile();
            BufferedWriter bw = new BufferedWriter(new FileWriter(link_error_file));
            for(int i=0; i<error_row; i++){                
                bw.write(error_table[i][0]+"\t"+error_table[i][1]);
                bw.write("\n");
            }
            bw.close();
        }catch(IOException e){
            System.out.println("Writing to error file failed");
        }
        
    }
        /**
        * Creates a text file for the symbol file and dumps the current contents 
        * of the symbol table to the file.
        * <p>
        * <b>Change Log:</b><br>
        * 4/24/08 - Initial Code - Yogesh Jindal<br>
        * 4/26/08 - Documentation Revised - Peter Dietz<br>
        * <p>
        * <b>Error Conditions Tested:</b><br>
        * INTERNAL: Writing to error file failed<br>
        * <b>Date of module being installed:</b> 4/24/08
        * @author Yogesh Jindal
        */
    public void addToSymbolFile(){        
        try{
            link_symbol_file.createNewFile();
            BufferedWriter bw = new BufferedWriter(new FileWriter(link_symbol_file));
            for(int i=0; i<symbol_row; i++){                
                bw.write(symbol_table[i][0]+"\t"+symbol_table[i][1]+"\t"+symbol_table[i][2]+"\t"+symbol_table[i][3]);
                bw.write("\n");
            }
            bw.close();
        }catch(IOException e){
            System.out.println("Writing to error file failed");
        }
        
    }
    
    protected String getLcOfLabel(String label){
        for(int index=0; index<symbol_row; index++){
            if(symbol_table[index][0].compareTo(label)==0){
                return symbol_table[index][1];
            }
        }
        return "-100";
    }
    public static void main(String[] args){
        
    }
}

